# iflytek_tts_client.py
# 封装讯飞 TTS WebSocket 客户端，提供 async 生成器流式返回音频数据

import hashlib
import base64
import time
import json
import asyncio
import websockets
import ssl
from urllib.parse import urlencode
import hmac

class IflytekTTSClient:
    def __init__(self, app_id, api_key, api_secret):
        self.app_id = app_id
        self.api_key = api_key
        self.api_secret = api_secret
        self.host = "tts-api.xfyun.cn"
        self.base_url = f"wss://{self.host}/v2/tts"

    def _get_auth_url(self):
        date = time.strftime("%a, %d %b %Y %H:%M:%S GMT", time.gmtime())
        signature_origin = f"host: {self.host}\ndate: {date}\nGET /v2/tts HTTP/1.1"
        signature_sha = hmac.new(self.api_secret.encode('utf-8'), signature_origin.encode('utf-8'), digestmod=hashlib.sha256).digest()
        signature = base64.b64encode(signature_sha).decode('utf-8')

        authorization_origin = f'api_key="{self.api_key}", algorithm="hmac-sha256", headers="host date request-line", signature="{signature}"'
        authorization = base64.b64encode(authorization_origin.encode('utf-8')).decode('utf-8')

        params = urlencode({
            "authorization": authorization,
            "date": date,
            "host": self.host
        })
        return self.base_url + "?" + params

    async def stream_text_to_pcm(self, text):
        url = self._get_auth_url()

        async with websockets.connect(url, ssl=ssl.SSLContext()) as ws:
            frame = {
                "common": {"app_id": self.app_id},
                "business": {
                    "aue": "lame", #raw
                    "auf": "audio/L16;rate=16000",
                    "vcn": "aisjiuxu",
                    "tte": "utf8"
                },
                "data": {
                    "status": 2,
                    "text": base64.b64encode(text.encode('utf-8')).decode('utf-8')
                }
            }

            await ws.send(json.dumps(frame))

            while True:
                resp = await ws.recv()
                resp_data = json.loads(resp)

                if resp_data.get('code') != 0:
                    raise Exception(f"TTS error: {resp_data.get('message')}")

                # audio = base64.b64decode(resp_data['data']['audio'])
                # yield audio
                audio_base64 = resp_data['data']['audio']
                #print(f"🟢 接收到音频 base64 长度: {len(audio_base64)}, 前20位: {audio_base64}")
                yield resp_data['data']['audio']  # ✅ 返回 base64 字符串
                if resp_data['data']['status'] == 2:
                    break
